/*
 * ============================================================================
 *                   GNU Lesser General Public License
 * ============================================================================
 *
 *
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 *
 *
 *
 */
package rad.framework.seam;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import rad.framework.lang.ReflectionUtil;
import rad.framework.trace.Trace;

import org.jboss.seam.Seam;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.core.Expressions;
import org.jboss.seam.core.Expressions.ValueExpression;
import org.jboss.seam.framework.EntityController;

@Trace
public class AbstractPageBean extends EntityController {

	private ValueExpression<?> label;
	private ValueExpression<?> title;

	public AbstractPageBean(String pageflow, String page) {
		this.label = Expressions.instance().createValueExpression(
				"#{messages['" + pageflow + "_" + page + "_label']}");
		this.title = Expressions.instance().createValueExpression(
				"#{messages['" + pageflow + "_" + page + "_title']}");
	}

	public String getName() {
		return Seam.getComponentName(getClass());
	}

	public String getLabel() {
		return label.getValue().toString();
	}

	public String getTitle() {
		return title.getValue().toString();
	}

	//---------------------------------------------------------------------
	// lifecycle related
	//---------------------------------------------------------------------
	
	// TODO remove ???
	@Create
	public void create() {
		debug("Create: #0", this);
		logConversation();
	}

	@Destroy
	@BypassInterceptors
	public void destroy() {
		debug("Destroy: #0", this);
		logConversation();
	}
	
	protected void logConversation() {
		debug(
				"Conversation: root(#0) parent(#1) id(#2) long(#3) nested(#4)",
				getConversation().getRootId(), getConversation().getParentId(),
				getConversation().getId(), getConversation().isLongRunning(),
				getConversation().isNested());
	}
	
	//---------------------------------------------------------------------
	// TODO Page Parameters
	//---------------------------------------------------------------------
	
	private Object id;
	
	public Object getId() {
		return id;
	}

	public void setId(Object id) {
		this.id = id;
	}
	
	//---------------------------------------------------------------------
	// Page Actions
	//---------------------------------------------------------------------

	private List<ActionMetadata> actions;

	public List<ActionMetadata> getActions() {
		if (actions == null) {
			actions = new ArrayList<ActionMetadata>();
			List<Method> methods = ReflectionUtil.findMethodsByAnnotation(this.getClass(), Action.class);
			int sort = 1;
			for (Method method : methods) {
				Action annotation = method.getAnnotation(Action.class);
				ActionMetadata action = new ActionMetadata(method, annotation, sort++);
				actions.add(action);
			}
			ActionMetadata.sort(actions);
		}
		return actions;
	}

/*
	<ui:repeat value="#{page.actions}" var="action">
		<li>
			<a4j:htmlCommandLink type="submit" 
				value="#{action.label}"
				title="#{action.title}"
				rendered="#{action.rendered}"
				disabled="#{action.disabled}"
				action="#{page[action.value]}">
				<s:conversationId/>
			</a4j:htmlCommandLink>
		</li>
	</ui:repeat>
 */

	//---------------------------------------------------------------------
	// GoTo Page Navigations
	//---------------------------------------------------------------------
	
	private List<ActionMetadata> menus = new ArrayList<ActionMetadata>();

	public List<ActionMetadata> getMenus() {
		ActionMetadata.sort(menus);
		return menus;
	}

	protected void addMenu(MenuMetadata page) {
		menus.add(page);
		page.setSort(menus.size() + 1);
	}

	/*
		<ui:repeat value="#{page.menus}" var="menu">
			<li>
				<a4j:htmlCommandLink type="submit" 
					value="#{menu.label}"
					title="#{menu.title}"
					disabled="#{menu.disabled}"
					action="#{menu.value}">
					<s:conversationId/>
				</a4j:htmlCommandLink>
			</li>
		</ui:repeat>
	 */
	

	/**
	 * @param outcome - outcome for direct page navigation
	 */
	static public class MenuMetadata  extends ActionMetadata {

		public String outcome() {
			return getValue();
		}
		
		private boolean active = false;
		
		public boolean isActive() {
			return active;
		}

		public MenuMetadata(AbstractPageBean component,
				String pageflow, String page, boolean active, String rendered,
				String disabled) {
			super("goTo" + page, 0, new String[] { pageflow }, rendered,
					disabled, true);
			this.active = active;
			component.addMenu(this);
		}
		
		protected String getPrefix(String[] prefixes, String name) {
			name = name.replace("goTo", "");
			StringBuilder builder = new StringBuilder();
			for (String string : prefixes) {
				builder.append(string.replace(" ", ""));
				builder.append("_");
			}
			builder.append(name);
			builder.append("_");
			return builder.toString();
		}
	}
}
